home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Cream of the Crop 1
/
Cream of the Crop 1.iso
/
PROGRAM
/
CBGRX100.ARJ
/
COLORS.C
< prev
next >
Wrap
Text File
|
1992-04-10
|
10KB
|
398 lines
/**
** COLORS.C
**
** Copyright (C) 1992, Csaba Biegl
** 820 Stirrup Dr, Nashville, TN, 37221
** csaba@vuse.vanderbilt.edu
**
** This file is distributed under the terms listed in the document
** "copying.cb", available from the author at the address above.
** A copy of "copying.cb" should accompany this file; if not, a copy
** should be available from where this file was obtained. This file
** may not be distributed without a verbatim copy of "copying.cb".
** You should also have received a copy of the GNU General Public
** License along with this program (it is in the file "copying");
** if not, write to the Free Software Foundation, Inc., 675 Mass Ave,
** Cambridge, MA 02139, USA.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**/
#include "grx.h"
#include "libgrx.h"
#include "interrup.h"
#include "gmalloc.h"
#include <string.h>
#include <stdlib.h>
typedef struct {
unsigned int n:6;
unsigned int state:2; /* 0=free, 1=shared, 2=writable */
unsigned char r;
unsigned char g;
unsigned char b;
} color;
#define C_FREE 0 /* free color */
#define C_SHARED 1 /* shared (by GrAllocColor) */
#define C_WRITABLE 2 /* writable (by GrAllocCell) */
#define KEEPBITS(v,n) \
v = ((v += (0x80 >> n)) > 0xff) ? \
(0xff ^ (0xff >> n)) : \
(v & (0xff ^ (0xff >> n)))
static color *colortable = NULL; /* color info table */
static int maxused; /* max used index in table */
static int freecolors; /* number of free colors */
static int whitecolor; /* index of white color */
static int RGBmode; /* set when in RGB mode */
static int lastcolors = -1; /* # of colors last initted to */
#define init_done() (lastcolors == _GrNumColors)
static void setcolor(int c,int r,int g,int b)
{
REGISTERS regs;
switch(_GrAdapterType) {
case GR_EGA:
regs.r_ax = 0x1000;
regs.r_bx = c & 0x0f;
regs.r_bx |= ((r & 0x40) << 7) | ((r & 0x80) << 3);
regs.r_bx |= ((g & 0x40) << 6) | ((g & 0x80) << 2);
regs.r_bx |= ((b & 0x40) << 5) | ((b & 0x80) << 1);
int10(®s);
break;
case GR_VGA:
if(_GrNumColors == 16) {
regs.r_ax = 0x1000;
regs.r_bx = (c & 0x0f) | ((c & 0x0f) << 8);
int10(®s);
}
#ifdef __GNUC__
asm volatile(
"cli \n"
"movl %0,%%eax \n"
"movl $0x3c8,%%edx \n"
"outb %%al,%%dx \n"
"inb $0x80,%%al \n"
"incl %%edx \n"
"movl %1,%%eax \n"
"shrb $2,%%al \n"
"outb %%al,%%dx \n"
"inb $0x80,%%al \n"
"movl %2,%%eax \n"
"shrb $2,%%al \n"
"outb %%al,%%dx \n"
"inb $0x80,%%al \n"
"movl %3,%%eax \n"
"shrb $2,%%al \n"
"outb %%al,%%dx \n"
"sti \n"
: /* NOTHING */
: "g" (c), "g" (r), "g" (g), "g" (b)
: "ax", "dx"
);
#elif defined(__TURBOC__)
disable();
outportb(0x3c8,c);
inportb(0x80);
outportb(0x3c9,(r >> 2));
inportb(0x80);
outportb(0x3c9,(g >> 2));
inportb(0x80);
outportb(0x3c9,(b >> 2));
enable();
#else
regs.r_ax = 0x1010;
regs.r_bx = c & 0xff;
regs.r_dx = ((r & 0xfc) << 6);
regs.r_cx = ((g & 0xfc) << 6) | ((b & 0xfc) >> 2);
int10(®s);
#endif
break;
}
colortable[c].r = r;
colortable[c].g = g;
colortable[c].b = b;
}
static int initcolors(void)
{
int whitevalue;
if((_GrCurrentMode >= GR_320_200_graphics) && !init_done()) {
switch(_GrNumColors) {
#if (GRXPLANES & 16)
case 32768:
#endif
case 2:
whitecolor = _GrNumColors - 1;
freecolors = 0;
RGBmode = TRUE;
maxused = 0;
break;
case 256:
case 16:
whitecolor = 15;
whitevalue = (_GrAdapterType == GR_EGA) ? 0xc0 : 0xfc;
if((_GrNumColors > lastcolors) && (colortable != NULL)) {
_GrFree(colortable);
colortable = NULL;
}
if(colortable == NULL) {
colortable = _GrMalloc(sizeof(color) * _GrNumColors);
if(colortable == NULL) return(FALSE);
}
memset(colortable,0,(sizeof(color) * _GrNumColors));
colortable[0].state = C_SHARED;
setcolor(0,0,0,0);
colortable[whitecolor].state = C_SHARED;
setcolor(whitecolor,whitevalue,whitevalue,whitevalue);
freecolors = _GrNumColors - 2;
maxused = whitecolor + 1;
RGBmode = FALSE;
break;
}
lastcolors = _GrNumColors;
}
return(init_done() ? TRUE : FALSE);
}
void GrResetColors(void)
{
lastcolors = (lastcolors >= _GrNumColors) ? (_GrNumColors + 1) : (-1);
initcolors();
}
void GrRefreshColors(void)
{
color *c;
int n;
if(lastcolors != _GrNumColors)
initcolors();
else for(n = 0,c = colortable; n < maxused; n++,c++)
if(c->state != C_FREE) setcolor(n,c->r,c->g,c->b);
}
void GrSetRGBcolorMode(void)
{
color *c;
int n;
if((init_done() || initcolors()) && !RGBmode &&
(_GrAdapterType == GR_VGA) &&
(_GrNumColors == 256)) {
for(n = 0,c = colortable; n < 256; n++,c++) {
c->state = C_SHARED;
c->n = 1;
setcolor(n,(n & 0xe0),((n << 3) & 0xe0),((n << 6) & 0xc0));
}
freecolors = 0;
whitecolor = 255;
RGBmode = TRUE;
maxused = 256;
}
}
int GrNumColors(void)
{
return(_GrNumColors);
}
int GrNumFreeColors(void)
{
if(!init_done()) initcolors();
return(freecolors);
}
int GrWhite(void)
{
return((init_done() || initcolors()) ? whitecolor : GrNOCOLOR);
}
int GrBlack(void)
{
return((init_done() || initcolors()) ? 0 : GrNOCOLOR);
}
int GrAllocColor(int r,int g,int b)
{
color *c;
int err,minerr;
int n,free = (-1);
if(!init_done() && !initcolors()) return(GrNOCOLOR);
if(RGBmode) switch(_GrNumColors) {
#if (GRXPLANES & 16)
case 32768:
KEEPBITS(r,5);
KEEPBITS(g,5);
KEEPBITS(b,5);
return((r << 7) | (g << 2) | (b >> 3));
#endif
case 256:
KEEPBITS(r,3);
KEEPBITS(g,3);
KEEPBITS(b,2);
return(r | (g >> 3) | (b >> 6));
case 2:
return(((r*30 + g*59 + b*11) >= 128*100) ? 1 : 0);
default:
return(GrNOCOLOR);
}
switch(_GrAdapterType) {
case GR_EGA:
KEEPBITS(r,2);
KEEPBITS(g,2);
KEEPBITS(b,2);
break;
case GR_VGA:
KEEPBITS(r,6);
KEEPBITS(g,6);
KEEPBITS(b,6);
break;
default:
return(GrNOCOLOR);
}
for(n = 0,c = colortable; n < maxused; n++,c++) {
switch(c->state) {
case C_SHARED:
if((c->r != r) || (c->g != g) || (c->b != b)) break;
c->n++;
return(n);
case C_FREE:
free = n;
break;
}
}
if((free < 0) && (maxused < _GrNumColors))
free = maxused++;
if(free >= 0) {
colortable[free].state = C_SHARED;
colortable[free].n = 1;
setcolor(free,r,g,b);
freecolors--;
return(free);
}
minerr = 3*32*32;
for(n = 0,c = colortable; n < _GrNumColors; n++,c++) {
if(c->state == C_SHARED) {
err = ((c->r - r) >> 2) * (c->r - r) +
((c->g - g) >> 2) * (c->g - g) +
((c->b - b) >> 2) * (c->b - b);
if(err <= minerr) {
minerr = err;
free = n;
}
}
}
if(free >= 0) {
colortable[free].n++;
return(free);
}
return(GrNOCOLOR);
}
int GrAllocCell(void)
{
int n,free = (-1);
if((init_done() || initcolors()) && !RGBmode && (freecolors > 0)) {
for(n = 0; n < maxused; n++) {
if(colortable[n].state == C_FREE) {
free = n;
break;
}
}
if(free < 0) free = maxused++;
colortable[free].state = C_WRITABLE;
colortable[free].n = 1;
freecolors--;
return(free);
}
return(GrNOCOLOR);
}
void GrFreeColor(int n)
{
color *c;
if(init_done() && !RGBmode &&
((unsigned)n < (unsigned)_GrNumColors) &&
((c = &colortable[n])->state != C_FREE)) {
if(c->n > 0) c->n--;
if(c->n == 0) c->state = C_FREE;
}
}
void GrSetColor(int n,int r,int g,int b)
{
color *c;
if((init_done() || initcolors()) && !RGBmode &&
((unsigned)n < (unsigned)_GrNumColors)) {
c = &colortable[n];
switch(c->state) {
case C_SHARED:
if(c->n > 0) return;
break;
case C_FREE:
if(n >= maxused) maxused = n + 1;
freecolors--;
break;
}
c->state = C_WRITABLE;
c->n = 1;
switch(_GrAdapterType) {
case GR_EGA:
KEEPBITS(r,2);
KEEPBITS(g,2);
KEEPBITS(b,2);
break;
case GR_VGA:
KEEPBITS(r,6);
KEEPBITS(g,6);
KEEPBITS(b,6);
break;
}
setcolor(n,r,g,b);
}
}
void GrQueryColor(int n,int *r,int *g,int *b)
{
color *c;
if(init_done() && ((unsigned)n < (unsigned)_GrNumColors)) {
if(colortable == NULL) switch(_GrNumColors) {
#if (GRXPLANES & 16)
case 32768:
*r = (n >> 7) & 0xf8;
*g = (n >> 2) & 0xf8;
*b = (n << 3) & 0xf8;
return;
#endif
case 2:
*r = *g = *b = (n ? 255 : 0);
return;
default:
*r = *g = *b = 0;
return;
}
c = &colortable[n];
*r = c->r;
*g = c->g;
*b = c->b;
}
}